package com.xuyuan.json.jsonpath;

import com.fasterxml.jackson.core.type.TypeReference;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.xuyuan.json.jackson.custom.Bodys;
import com.xuyuan.json.jackson.entity.Person;
import com.xuyuan.util.JsonPathUtil;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * @author xuyuan
 * @see JsonPath
 */
public class JsonPathRead {
    private static final String FILE_PATH = "C:/Software/IDEA2022/workspace/reflect/classes" + File.separator + "jsonpath.txt";
    private static String json;
    private static Configuration config;

    static {
        try {
            json = new String(Files.readAllBytes(Paths.get(FILE_PATH)));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        config = Configuration.defaultConfiguration().addOptions(Option.AS_PATH_LIST);
    }

    /**
     * 1. JsonPath的操作符号
     * <p> $ ：根节点
     * <p> @ ：当前节点
     * <p> * ：所有子节点
     * <p> ?() ：过滤条件
     * <p>[] ：索引，支持数字索引和范围
     * <p>[,]:范围
     * <p> .. ：递归
     * <p>.xxx ：属性
     * <p>
     * <p>
     * 2. 过滤运算操作符号
     * <p> ==、!=、>、>=、<、<=、in、nin、size、empty、=~、
     * <p> =~ 匹配正则表达式[?(@.name =~ /foo.*?/i)]
     * <p>
     * 3. 函数操作
     * <p>min()、max()、avg()、sum()、length()、stddev()
     * <p>
     * <p>
     */
    @Test
    public void test() throws Exception {
        System.out.println(JsonPath.using(config).parse(json).read("$").toString());

        System.out.println(JsonPath.read(json, "$.store.bicycle.color").toString());

        System.out.println(JsonPath.read(json, "$.store.book[?(@.price < 10)].author").toString());

        System.out.println(JsonPath.read(json, "$.store.*").toString());

        System.out.println(JsonPath.read(json, "$.store.book[0].author").toString());

        System.out.println(JsonPath.read(json, "$.store.book[0,1].author").toString());

        System.out.println(JsonPath.read(json, "$.store.book[?(@.category=='fiction')].author").toString());

        System.out.println(JsonPath.read(json, "$..book[-2]").toString());

        System.out.println(JsonPath.read(json, "$..price").toString());
    }

    /**
     * Jackson/Gson/Fastjson 主要是用于序列化/反序列化，简单对象的键值获取处理。对于JsonPath的使用，主要用在复杂对象指定路径下的键值获取。
     * JsonPath的使用案例
     * <p> 解析JSON
     * <p> 其他的案例学习
     * <p> 其他的API学习
     *
     * @throws Exception
     */
    @Test
    public void test2() throws Exception {
        // 获取指定的Json的key/value
        // 使用JsonPath替换所有键对应下的值,简单对象
        DocumentContext context = JsonPath.using(config).parse(json);
        context.set("$..price", 2.00);

        // 复杂化了
        // List<String> paths = context.read("$..price", List.class);
        // System.out.println(paths);
        // for (String path : paths) {
        //     try {
        //         context.set(path, 2.00);
        //     } catch (PathNotFoundException e) {
        //         // 忽略路径不存在的异常
        //     }
        // }
        // System.out.println(context.jsonString());

        String s = JsonPathUtil.replaceAllKey(json, "price", 2.00);
        System.out.println(s);

        Bodys<Person> personBodys = new Bodys<>();
        personBodys.setCommonField("1111");
        Person person = new Person();
        person.setMyName("xxx");
        person.setMyHeight(172);
        personBodys.setBody(person);

        Person person1 = JsonPathUtil.replaceAllKey(person, "myName", "xuyuan");
        System.out.println(person1);

        Bodys<Person> personBodys1 = JsonPathUtil.replaceAllKeyWithGeneric(personBodys, "myName", "xuyuan", new TypeReference<Bodys<Person>>() {
        });
        System.out.println(personBodys1);
    }

}
